/**
 * ResizeFilterControl.java
 * 
 * @date: 2012-02-15
 * @author: Xiaoyu Guo (MUN# 200982155)
 * This file is part of the course project for COMP 6752, 
 * Application of Computer Graphics. All the file is written
 * by myself.
 */
package mun.cs6752.project.filter.resize;

import java.awt.BorderLayout;

import javax.swing.JPanel;

import mun.cs6752.project.filter.abstractClasses.AbstractImageFilterControl;
import mun.cs6752.project.filter.interfaces.IImageFilter;
import mun.cs6752.project.filter.interfaces.IImageFilterParameter;
import mun.cs6752.project.filter.interfaces.IImageProvider;
import mun.cs6752.project.filter.resize.ResizeFilterParameter.ResizeMethod;
import java.awt.GridBagLayout;
import javax.swing.JLabel;
import java.awt.GridBagConstraints;
import javax.swing.JSpinner;
import java.awt.Insets;
import javax.swing.JCheckBox;
import javax.swing.JButton;
import javax.swing.JComboBox;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;

/**
 * @author Xiaoyu Guo
 *
 */
public class ResizeFilterControl extends AbstractImageFilterControl {
    private static final long serialVersionUID = 7431108333370315556L;


    /**
     * @param provider
     * @param filter
     */
    public ResizeFilterControl(IImageProvider provider, IImageFilter filter) {
        super(provider, filter);
    }
    
    private int newHeight;
    private int newWidth;
    private ResizeMethod method;
    private JComboBox cbSamplingMethod;
    private JSpinner spNewHeight;
    private JSpinner spNewWidth;
    
    
    @Override
    protected void initUI(){
        super.initUI();
        
        JPanel pnlControls = new JPanel();
        this.add(pnlControls, BorderLayout.CENTER);
        GridBagLayout gbl_pnlControls = new GridBagLayout();
        gbl_pnlControls.columnWidths = new int[]{0, 0, 0, 0};
        gbl_pnlControls.rowHeights = new int[]{0, 0, 0, 0, 0, 0, 0};
        gbl_pnlControls.columnWeights = new double[]{1.0, 1.0, 1.0, Double.MIN_VALUE};
        gbl_pnlControls.rowWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE};
        pnlControls.setLayout(gbl_pnlControls);
        
        JLabel lblWidth = new JLabel("Width");
        GridBagConstraints gbc_lblWidth = new GridBagConstraints();
        gbc_lblWidth.anchor = GridBagConstraints.EAST;
        gbc_lblWidth.insets = new Insets(0, 0, 5, 5);
        gbc_lblWidth.gridx = 0;
        gbc_lblWidth.gridy = 0;
        pnlControls.add(lblWidth, gbc_lblWidth);
        
        spNewWidth = new JSpinner();
        spNewWidth.setModel(new SpinnerNumberModel(new Integer(0), new Integer(0), null, new Integer(1)));
        spNewWidth.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent e) {
                setNewWidth(((SpinnerNumberModel)spNewWidth.getModel()).getNumber().intValue());
            }
        });
        GridBagConstraints gbc_spNewWidth = new GridBagConstraints();
        gbc_spNewWidth.gridwidth = 2;
        gbc_spNewWidth.fill = GridBagConstraints.HORIZONTAL;
        gbc_spNewWidth.insets = new Insets(0, 0, 5, 0);
        gbc_spNewWidth.gridx = 1;
        gbc_spNewWidth.gridy = 0;
        pnlControls.add(spNewWidth, gbc_spNewWidth);
        
        JLabel lblHeight = new JLabel("Height");
        GridBagConstraints gbc_lblHeight = new GridBagConstraints();
        gbc_lblHeight.anchor = GridBagConstraints.EAST;
        gbc_lblHeight.insets = new Insets(0, 0, 5, 5);
        gbc_lblHeight.gridx = 0;
        gbc_lblHeight.gridy = 1;
        pnlControls.add(lblHeight, gbc_lblHeight);
        
        spNewHeight = new JSpinner();
        spNewHeight.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent e) {
                setNewHeight(((SpinnerNumberModel)spNewHeight.getModel()).getNumber().intValue());
            }
        });
        spNewHeight.setModel(new SpinnerNumberModel(new Integer(0), new Integer(0), null, new Integer(1)));
        GridBagConstraints gbc_spNewHeight = new GridBagConstraints();
        gbc_spNewHeight.gridwidth = 2;
        gbc_spNewHeight.fill = GridBagConstraints.HORIZONTAL;
        gbc_spNewHeight.insets = new Insets(0, 0, 5, 0);
        gbc_spNewHeight.gridx = 1;
        gbc_spNewHeight.gridy = 1;
        pnlControls.add(spNewHeight, gbc_spNewHeight);
        
        JCheckBox chckbxProportional = new JCheckBox("Proportional");
        GridBagConstraints gbc_chckbxProportional = new GridBagConstraints();
        gbc_chckbxProportional.insets = new Insets(0, 0, 5, 5);
        gbc_chckbxProportional.anchor = GridBagConstraints.EAST;
        gbc_chckbxProportional.gridx = 1;
        gbc_chckbxProportional.gridy = 2;
        pnlControls.add(chckbxProportional, gbc_chckbxProportional);
        
        JButton btnSourceSize = new JButton("1x");
        btnSourceSize.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                setScaling(1.0F);
            }
        });
        GridBagConstraints gbc_btnSourceSize = new GridBagConstraints();
        gbc_btnSourceSize.insets = new Insets(0, 0, 5, 5);
        gbc_btnSourceSize.gridx = 0;
        gbc_btnSourceSize.gridy = 3;
        pnlControls.add(btnSourceSize, gbc_btnSourceSize);
        
        JButton btnDoubleSize = new JButton("2x");
        btnDoubleSize.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                setScaling(2.0F);
            }
        });
        GridBagConstraints gbc_btnDoubleSize = new GridBagConstraints();
        gbc_btnDoubleSize.insets = new Insets(0, 0, 5, 5);
        gbc_btnDoubleSize.gridx = 1;
        gbc_btnDoubleSize.gridy = 3;
        pnlControls.add(btnDoubleSize, gbc_btnDoubleSize);
        
        JButton btnTripleSize = new JButton("3x");
        btnTripleSize.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                setScaling(3.0F);
            }
        });
        GridBagConstraints gbc_btnTripleSize = new GridBagConstraints();
        gbc_btnTripleSize.insets = new Insets(0, 0, 5, 0);
        gbc_btnTripleSize.gridx = 2;
        gbc_btnTripleSize.gridy = 3;
        pnlControls.add(btnTripleSize, gbc_btnTripleSize);
        
        JButton btnQuarterSize = new JButton("1/4");
        btnQuarterSize.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                setScaling(0.25F);
            }
        });
        GridBagConstraints gbc_btnQuarterSize = new GridBagConstraints();
        gbc_btnQuarterSize.insets = new Insets(0, 0, 5, 5);
        gbc_btnQuarterSize.gridx = 0;
        gbc_btnQuarterSize.gridy = 4;
        pnlControls.add(btnQuarterSize, gbc_btnQuarterSize);
        
        JButton btn1_3Size = new JButton("1/3");
        btn1_3Size.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                setScaling(0.33333333F);
            }
        });
        GridBagConstraints gbc_btn1_3Size = new GridBagConstraints();
        gbc_btn1_3Size.insets = new Insets(0, 0, 5, 5);
        gbc_btn1_3Size.gridx = 1;
        gbc_btn1_3Size.gridy = 4;
        pnlControls.add(btn1_3Size, gbc_btn1_3Size);
        
        JButton btnHalfSize = new JButton("1/2");
        btnHalfSize.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                setScaling(0.5F);
            }
        });
        GridBagConstraints gbc_btnHalfSize = new GridBagConstraints();
        gbc_btnHalfSize.insets = new Insets(0, 0, 5, 0);
        gbc_btnHalfSize.gridx = 2;
        gbc_btnHalfSize.gridy = 4;
        pnlControls.add(btnHalfSize, gbc_btnHalfSize);
        
        JLabel lblSampling = new JLabel("Sampling");
        GridBagConstraints gbc_lblSampling = new GridBagConstraints();
        gbc_lblSampling.anchor = GridBagConstraints.EAST;
        gbc_lblSampling.insets = new Insets(0, 0, 0, 5);
        gbc_lblSampling.gridx = 0;
        gbc_lblSampling.gridy = 5;
        pnlControls.add(lblSampling, gbc_lblSampling);
        
        cbSamplingMethod = new JComboBox(ResizeMethod.values());
        cbSamplingMethod.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                setMethod((ResizeMethod)cbSamplingMethod.getSelectedItem());
                preview();
            }
        });
        GridBagConstraints gbc_cbSamplingMethod = new GridBagConstraints();
        gbc_cbSamplingMethod.gridwidth = 2;
        gbc_cbSamplingMethod.fill = GridBagConstraints.HORIZONTAL;
        gbc_cbSamplingMethod.gridx = 1;
        gbc_cbSamplingMethod.gridy = 5;
        pnlControls.add(cbSamplingMethod, gbc_cbSamplingMethod);
    }
    
    @Override
    protected void initValue(){
        super.initValue();
        if(provider.getSourceImage() != null){
            setNewHeight(provider.getSourceImage().getHeight());
            setNewWidth(provider.getSourceImage().getWidth());
        } else {
            setNewHeight(0);
            setNewWidth(0);
        }
        setMethod(ResizeMethod.Bicubic);
    }
    
    private void setScaling(float ratio){
        if(provider.getSourceImage() != null){
            setNewWidth(Math.round(provider.getSourceImage().getWidth() * ratio));
            setNewHeight(Math.round(provider.getSourceImage().getHeight() * ratio));
            preview();
        }
    }
    
    private void setNewWidth(int value){
        if(value != this.newWidth){
            this.newWidth = value;
            this.spNewWidth.setValue(value);
        }
    }
    
    private void setNewHeight(int value){
        if(value != this.newHeight){
            this.newHeight = value;
            this.spNewHeight.setValue(value);
        }
    }
    
    private void setMethod(ResizeMethod method){
        if(!method.equals(this.method)){
            this.method = method;
            cbSamplingMethod.setSelectedItem(method);
        }
    }

    /* (non-Javadoc)
     * @see mun.cs6752.project.filter.interfaces.IImageFilterControl#getParameter()
     */
    @Override
    public IImageFilterParameter getParameter() {
        return new ResizeFilterParameter(newWidth, newHeight, method);
    }

}
